﻿/*
	版本号：1.0.0
	日期:2018-06-20
	作者：wj
	联系邮箱:3228798988@qq.com有建议请联系

	功能描述：
	1, 计算后样式封装  直接调用fetchComputedStyle()方法，传两个参数：第一个为要获取的对象，第二个为对象的属性!
	2, 动画方法  直接调用anmate();
		可传入五个参数: object  json  time  tween function;
		参数：必须传三个参数以上，第一个为对象，第二个为JSON格式目标点的属性值，第三个为动画时间!
			可传可不传第四个参数，第四个参数要么是字符串的运动名词，要么是回调用函数
*/

//动画方法
function animate(ele, targetJSON, times, tweenName, callback){
	//判断参数
	if(typeof arguments[0] != 'object' || typeof arguments[1] != 'object' || typeof arguments[2] != 'number'){
		throw new Error('必须传三个参数以上，第一个为对象，第二个为JSON格式目标点的属性值，第三个为动画时间!')
	}else if(arguments.length == 3){
		tweenName = 'linear';
		callback = null;
	}else if(arguments.length == 4){
		switch(typeof arguments[3]){
			case 'string':
				callback = null;
				break;
			case 'function':
				callback = arguments[3];
				tweenName = 'linear';
				break;
			default:
				throw new Error('第四个参数要么是运动描述词，要么是函数')
		}
	}

	//加一个锁, 强制给元素加了一个属性叫lock
	ele.lock = true;

	//运动间隔
	var interval = 10;

	//总次数，帧数  设定运动时间间隔 20
	var maxCount = parseInt(times / interval);

	//求出元素初始值
	var initialJSON = {};//先定义一个空对象然后去添加项
	for(var k in targetJSON){//对应遍历目标点的属性
		initialJSON[k] = fetchComputedStyle(ele, k);
	}
	
	//步长,每一次走多少像素！
	//var stepJSON = {};
	//变化量
	var changeJSON = {};
	for(var k in targetJSON){//600px - 40
		//stepJSON[k] = (parseFloat(targetJSON[k]) - initialJSON[k]) / maxCount;
		changeJSON[k] = (parseFloat(targetJSON[k]) - initialJSON[k]);
	};

	//定义定时器
	var timer = null;
	//定义一个计数器
	var number = 0;
	//清除一下定时器
	clearInterval(timer);
	//开定时器
	timer = setInterval(function(){
		//累加 初始值不断累加步长
		for(var k in targetJSON){
			//initialJSON[k] += stepJSON[k];
			//判断是否为透明属性
			//console.log(k)
			if(k == 'opacity'){
				/*
				第一个参数t表示当前帧  number!
				第二个参数b表示起始位置  初始点  initialJSON[k]
				第三个参数c表示变化量 = 目标位置 - 起始位置  并不是步长
				第四个参数d表示总帧数
				*/
				ele.style[k] = Tween[tweenName](number, initialJSON[k], changeJSON[k], maxCount);
				//兼容IE低版本的
				ele.style.filter = 'alpha(opacity='+ Tween[tweenName](number, initialJSON[k], changeJSON[k], maxCount)*100 +')';
			}else{
				ele.style[k] = Tween[tweenName](number, initialJSON[k], changeJSON[k], maxCount) + 'px';
				//document.title = Tween[tweenName](number, initialJSON[k], changeJSON[k], maxCount);
			}	
		}
		
		//停止定时器
		number++;
		if(maxCount == number){
			clearInterval(timer);
			for(var k in targetJSON){
				if(k == 'opacity'){
					ele.style[k] = parseFloat(targetJSON[k]);
					//兼容IE低版本的
					ele.style.filter = 'alpha(opacity='+ parseFloat(targetJSON[k])*100 +')';
				}else{
					ele.style[k] = parseFloat(targetJSON[k]) + 'px';
					//console.log(parseFloat(targetJSON[k]))
				}	
			}
			
			//开锁
			ele.lock = false;
			//短路思维
			callback && callback.call(ele);
		}
	}, interval);
};

//计算后样式方法
function fetchComputedStyle(obj, property){//接收两个参数，一个为对象一个为属性
	//检测它的能力
	if(window.getComputedStyle){
		return parseFloat(getComputedStyle(obj)[property]);
	}else{
		return parseFloat(obj.currentStyle[property]);
	}
};


//缓冲计算公式
var Tween = {
    linear: function(t, b, c, d) {
        return c * t / d + b;
    },
    //二次的
    quadEaseIn: function(t, b, c, d) {
        return c * (t /= d) * t + b;
    },
    quadEaseOut: function(t, b, c, d) {
        return -c * (t /= d) * (t - 2) + b;
    },
    quadEaseInOut: function(t, b, c, d) {
        if ((t /= d / 2) < 1) return c / 2 * t * t + b;
        return -c / 2 * ((--t) * (t - 2) - 1) + b;
    },
    //三次的
    qubicEaseIn: function(t, b, c, d) {
        return c * (t /= d) * t * t + b;
    },
    qubicEaseOut: function(t, b, c, d) {
        return c * ((t = t / d - 1) * t * t + 1) + b;
    },
    qubicEaseInOut: function(t, b, c, d) {
        if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
        return c / 2 * ((t -= 2) * t * t + 2) + b;
    },
    //四次的
    quartEaseIn: function(t, b, c, d) {
        return c * (t /= d) * t * t * t + b;
    },
    quartEaseOut: function(t, b, c, d) {
        return -c * ((t = t / d - 1) * t * t * t - 1) + b;
    },
    quartEaseInOut: function(t, b, c, d) {
        if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
        return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
    },
    quartEaseIn: function(t, b, c, d) {
        return c * (t /= d) * t * t * t * t + b;
    },
    quartEaseOut: function(t, b, c, d) {
        return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
    },
    quartEaseInOut: function(t, b, c, d) {
        if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
        return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
    },
    //正弦的
    sineEaseIn: function(t, b, c, d) {
        return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
    },
    sineEaseOut: function(t, b, c, d) {
        return c * Math.sin(t / d * (Math.PI / 2)) + b;
    },
    sineEaseInOut: function(t, b, c, d) {
        return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
    },
    expoEaseIn: function(t, b, c, d) {
        return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
    },
    expoEaseOut: function(t, b, c, d) {
        return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
    },
    expoEaseInOut: function(t, b, c, d) {
        if (t == 0) return b;
        if (t == d) return b + c;
        if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
        return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
    },
    circEaseIn: function(t, b, c, d) {
        return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
    },
    circEaseOut: function(t, b, c, d) {
        return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
    },
    circEaseInOut: function(t, b, c, d) {
        if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
        return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
    },
    elasticEaseIn: function(t, b, c, d, a, p) {
        if (t == 0) return b;
        if ((t /= d) == 1) return b + c;
        if (!p) p = d * .3;
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else var s = p / (2 * Math.PI) * Math.asin(c / a);
        return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
    },
    elasticEaseOut: function(t, b, c, d, a, p) {
        if (t == 0) return b;
        if ((t /= d) == 1) return b + c;
        if (!p) p = d * .3;
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else var s = p / (2 * Math.PI) * Math.asin(c / a);
        return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
    },
    elasticEaseInOut: function(t, b, c, d, a, p) {
        if (t == 0) return b;
        if ((t /= d / 2) == 2) return b + c;
        if (!p) p = d * (.3 * 1.5);
        if (!a || a < Math.abs(c)) {
            a = c;
            var s = p / 4;
        } else var s = p / (2 * Math.PI) * Math.asin(c / a);
        if (t < 1) return -.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
        return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
    },
    //冲过头系列
    backEaseIn: function(t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        return c * (t /= d) * t * ((s + 1) * t - s) + b;
    },
    backEaseOut: function(t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
    },
    backEaseInOut: function(t, b, c, d, s) {
        if (s == undefined) s = 1.70158;
        if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
        return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
    },
    //弹跳系列
    bounceEaseIn: function(t, b, c, d) {
        return c - Tween.bounceEaseOut(d - t, 0, c, d) + b;
    },
    bounceEaseOut: function(t, b, c, d) {
        if ((t /= d) < (1 / 2.75)) {
            return c * (7.5625 * t * t) + b;
        } else if (t < (2 / 2.75)) {
            return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
        } else if (t < (2.5 / 2.75)) {
            return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
        } else {
            return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
        }
    },
    bounceEaseInOut: function(t, b, c, d) {
        if (t < d / 2) return Tween.bounceEaseIn(t * 2, 0, c, d) * .5 + b;
        else return Tween.bounceEaseOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
    }
}